package com.erlang4j.example.messageProcessor;

import static com.erlang4j.api.Erlang4jMessageLanguage.atom;
import static com.erlang4j.api.Erlang4jMessageLanguage.binding;

import com.erlang4j.api.Erlang4jFactory;
import com.erlang4j.api.IErlang4j;
import com.erlang4j.api.IGetData;
import com.erlang4j.api.adapters.MessageAdapter;
import com.erlang4j.api.process.IProcess;
import com.erlang4j.api.process.IProcessWithState;

/**
 * <p>
 * This is some example code that shows the ideas in how you should use Erlang4J.
 * </p>
 * 
 * @author Phil
 */
public class ExampleMessageProcessor {

	/**
	 * This will take erlang objects, if it finds a pattern that matches it will execute the handler for that pattern
	 */

	private static void ioFormat(String format, Object... parameters) {
		System.out.println(String.format(format, parameters));
	}

	public static void main(String[] args) throws Exception {
		// There must be an erlang node, or virtual machine, called ErlangVM,
		// and its using "cookie" as its cookie

		IErlang4j erlang4j = Erlang4jFactory.make("ErlangVm", "cookie");

		IProcess process = erlang4j.spawn( //
				new MessageAdapter("{Pid,{status,Status}}") {
					@Override
					public void process(IProcessWithState process, IGetData data) throws Exception {
						ioFormat("Status: %s from Pid %s", data.getString("Status"), data.getPid("Pid"));
					}

				}, new MessageAdapter("{Pid,{command1,Param1,Param2}}") {
					@Override
					public void process(IProcessWithState process, IGetData data) throws Exception {
						ioFormat("Command1(%s,%s) from Pid %s", data.getString("Param1"), data.getString("Param2"), data.getPid("Pid"));
					}
				}, new MessageAdapter("Any") {
					@Override
					public void process(IProcessWithState process, IGetData data) throws Exception {
						ioFormat("unexpected command %s", data.getRaw("Any"));
					}
				});

		// At this point there is a thread that is up and running listening to
		// the mailbox
		// This thread is expecting messages from the same Pid given the initial
		// binding (see the spawn method in ExampleMessageProcessor)
		// If a message came from elsewhere the "Any" clause would still fire

		// This is one way of composing messages and sending them to the mailbox
		// at the pid for the messageProcessorThread to handle
		String serverName = "server";
		process.send(serverName, "Self", atom("wierdCommandAtom"));
		process.send(serverName, "{Self,{status,P0}}", "some other status string");
		process.send(serverName, "{Self,{command1,P0,P1}}", "param1", "param2");

		// This is a more verbose way of composing messages and sending them to
		// the mailbox at the pid for the messageProcessorThread to handle
		process.sendWithBinding(serverName, "{Self,{status,Status}}", binding("Status", "some status string"));
		process.sendWithBinding(serverName, "{Self,{command1,Param1,Param2}}", binding("Param1", "param1", "Param2", "param2"));

		// wait for the messageProcessorThread to handle the messages
		Thread.sleep(1000);

	}
}
